#include "ClassSkillProxy.h"



#include <CharacterItem.h>



#include <QDebug>
#include <QRegExp>



ClassSkillProxy::ClassSkillProxy(QObject *parent) :
    AbstractItemProxy(parent)
{
}



int ClassSkillProxy::columnCount(const QModelIndex &proxyParent) const
{
    Q_UNUSED(proxyParent);
    return 1;
}


QVariant ClassSkillProxy::data(const QModelIndex &proxyIndex, int role) const
{
    QModelIndex sourceIndex = mapToSource(proxyIndex);
    QModelIndex sourceNameIndex = sourceIndex.sibling(sourceIndex.row(), AbstractItem::NameData);
    switch (role)
    {
    case Qt::DisplayRole:   return sourceNameIndex.data(Qt::DisplayRole);
    case Qt::EditRole:      return sourceIndex.data(Qt::EditRole);
    case Qt::CheckStateRole: break;
    default: return QVariant();
    }

    if (isClassSkill(proxyIndex)) return Qt::Checked;

    return Qt::Unchecked;

}


bool ClassSkillProxy::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (!index.isValid() || role != Qt::CheckStateRole) return false;

    QModelIndex sourceClassSkill = classSkillIndex(index);
    qDebug() << Q_FUNC_INFO << sourceClassSkill.data(Qt::EditRole) << value;
    if (value.toInt() == Qt::Checked && sourceClassSkill.isValid()) return false;
    else if (value.toInt() == Qt::Unchecked && !sourceClassSkill.isValid()) return false;
    else if (value.toInt() == Qt::PartiallyChecked) return false;

    ItemModel* model = itemModel();
    if (!model) return false;


    if (!value.toBool())
    {
        QModelIndex sourceClassSkills = sourceClassSkill.parent();
        qDebug() << sourceClassSkills.data(Qt::EditRole);
        if (!sourceClassSkills.isValid()) return false;

        model->removeRows(sourceClassSkill.row(), 0, sourceClassSkills);
        emit dataChanged(index, index);
        return true;
    }


    CharacterItem* root = dynamic_cast<CharacterItem*>(model->rootItem());
    if (!root) return false;

    QString pattern = QString("%1.Class Skill").arg(root->name());
    QModelIndex matchStart = model->index(0, AbstractItem::IdData, QModelIndex());
    QModelIndexList foundIndexes = model->match(matchStart,
                                                Qt::EditRole,
                                                pattern,
                                                1,
                                                Qt::MatchExactly);

    QModelIndex sourceClassSkills;
    if (foundIndexes.isEmpty())
    {
        int row = model->rowCount(QModelIndex());
        model->insertRow(row,QModelIndex());
        sourceClassSkills = model->index(row, AbstractItem::NameData, QModelIndex());
        model->setData(sourceClassSkills, "Class Skills", Qt::EditRole);
    }
    else
    {
        sourceClassSkills = foundIndexes.first();
    }

    int row = model->rowCount(sourceClassSkills);
    model->insertRow(row,sourceClassSkills);
    sourceClassSkill = model->index(row, AbstractItem::NameData, sourceClassSkills);

    QModelIndex sourceSkill = mapToSource(index);
    QModelIndex sourceName = sourceSkill.sibling(sourceSkill.row(), AbstractItem::NameData);
    model->setData(sourceClassSkill, sourceName.data(Qt::EditRole), Qt::EditRole);
    emit dataChanged(index,index);
    return false;
}


QVariant ClassSkillProxy::headerData(int section, Qt::Orientation orientation, int role) const
{
    Q_UNUSED(section);
    Q_UNUSED(orientation);
    if (role != Qt::DisplayRole) return QVariant();

    return tr("Skills");
}



Qt::ItemFlags ClassSkillProxy::flags(const QModelIndex &index) const
{
    return QAbstractProxyModel::flags(index) | Qt::ItemIsUserCheckable;
}


void ClassSkillProxy::remap()
{
    //qDebug() << Q_FUNC_INFO;
    beginResetModel();
    m_indexMap.clear();
    endResetModel();

    ItemModel* model = itemModel();
    if (!model) return;

    CharacterItem* root = dynamic_cast<CharacterItem*>(model->rootItem());
    if (!root || root->campaignName().isEmpty()) return;

    QString pattern = QString("%1.%2.Skill.([a-zA-Z0-9 ]+)").arg(root->name()).arg(root->campaignName());
    QModelIndex matchStart = model->index(0, AbstractItem::IdData, QModelIndex());
    QModelIndexList foundIndexes = model->match(matchStart,
                                                Qt::EditRole,
                                                pattern,
                                                -1,
                                                Qt::MatchRegExp |
                                                Qt::MatchRecursive);


    emit layoutAboutToBeChanged();
    foreach (QModelIndex foundIndex, foundIndexes)
    {
//        m_indexMap.insert(foundIndex.sibling(foundIndex.row(), AbstractItem::NameData),
//                          createIndex(foundIndex.row(), NameField, foundIndex.internalPointer()));
//        m_indexMap.insert(foundIndex,
//                          createIndex(foundIndex.row(), CheckedField, foundIndex.internalPointer()));
        m_indexMap.insert(foundIndex,
                          createIndex(foundIndex.row(), 0, foundIndex.internalPointer()));
    }
    emit layoutChanged();

}



bool ClassSkillProxy::isClassSkill(const QModelIndex &proxyIndex) const
{
    return classSkillIndex(proxyIndex).isValid();
}



QModelIndex ClassSkillProxy::classSkillIndex(const QModelIndex &proxyIndex) const
{
    QModelIndex sourceIndex = mapToSource(proxyIndex);
    if (!sourceIndex.isValid()) return QModelIndex();

    ItemModel* model = itemModel();
    if (!model) return QModelIndex();

    CharacterItem* root = dynamic_cast<CharacterItem*>(model->rootItem());
    if (!root || root->name().isEmpty()) return QModelIndex();

    QString pattern = QString("%1.Class Skill").arg(root->name());
    QModelIndex matchStart = model->index(0, AbstractItem::IdData, QModelIndex());
    QModelIndexList foundIndexes = model->match(matchStart,
                                                Qt::EditRole,
                                                pattern,
                                                1,
                                                Qt::MatchExactly);

    if (foundIndexes.isEmpty()) return QModelIndex();

    QModelIndex sourceNameIndex = sourceIndex.sibling(sourceIndex.row(), AbstractItem::NameData);

    pattern = QString("%1.%2").arg(pattern).arg(sourceNameIndex.data(Qt::EditRole).toString());
    matchStart = model->index(0, AbstractItem::IdData, foundIndexes.first());
    foundIndexes = model->match(matchStart,
                                Qt::EditRole,
                                pattern,
                                1,
                                Qt::MatchExactly);


    if (foundIndexes.isEmpty()) return QModelIndex();

    return foundIndexes.first();
}



